﻿using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using Dapper;
using Oracle.ManagedDataAccess.Client;
using Zzt.ExpertsCore.Domain.Entities;

namespace Zzt.ExpertsCore.Domain.Repository.Impl
{
    public class DapperUnitOfWork : IUnitOfWork
    {
        private readonly IDbConnection _connection;

        public IDbTransaction Transaction { get; }
        public string Area;

        public DapperUnitOfWork(DatabaseConfiguration configuration)
        {
            _connection = new OracleConnection(configuration.Connection);
            _connection.Open();

            Transaction = _connection.BeginTransaction();
            Area = configuration.AreaPrefix;
        }

        public void Commit()
        {
            try
            {
                Transaction.Commit();
            }
            catch
            {
                Transaction.Rollback();
                throw;
            }
            finally
            {
                Transaction.Dispose();
            }
        }

        public void Rollback() => Transaction.Rollback();

        public Task<IEnumerable<TModel>> QueryModel<TModel>(string cmd, object[] parameters)
        {
            return _connection.QueryAsync<TModel>(cmd, parameters, Transaction);
        }

        public Task<TModel> QueryModelFirstOrDefault<TModel>(string cmd, object[] parameters)
        {
            return _connection.QueryFirstOrDefaultAsync<TModel>(cmd, parameters, Transaction);
        }


        public string BuildTableName<TEntity>() where TEntity : BaseEntity
        {
            return $"{Area}_{nameof(TEntity)}";
        }

        public void Dispose()
        {
            _connection.Close();
            _connection?.Dispose();
            Transaction?.Dispose();
        }
    }
}
